"""
核反应堆子通道分析程序的辅助函数
"""

from CoolProp.CoolProp import PropsSI
import numpy as np
from constants.constants import DEFAULT_SATURATION_TEMP, DEFAULT_LATENT_HEAT

def get_fluid_properties(p, t, phase):
    """
    获取指定状态点的流体物性
    
    参数：
    p: float, 压力 (Pa)
    t: float, 温度 (K)
    phase: str, 相态 ('liquid' 或 'vapor')
    
    返回：
    dict, 包含密度、粘度和焓值的字典
    """
    try:
        # 确保参数在CoolProp的有效范围内
        p = max(611.655, min(p, 2.2064e7))  # 水的三相点到临界点压力范围
        t = max(273.16, min(t, 647.096))    # 水的三相点到临界点温度范围
        
        if phase == 'liquid':
            # 计算液相物性
            return {
                'density': PropsSI('D', 'P', p, 'T', t, 'Water'),    # 密度 (kg/m³)
                'viscosity': PropsSI('V', 'P', p, 'T', t, 'Water'),  # 动力粘度 (Pa·s)
                'enthalpy': PropsSI('H', 'P', p, 'T', t, 'Water'),   # 比焓 (J/kg)
                'specific_heat': PropsSI('C', 'P', p, 'T', t, 'Water'),  # 比热容 (J/kg·K)
                'thermal_conductivity': PropsSI('L', 'P', p, 'T', t, 'Water')  # 导热系数 (W/m·K)
            }
        else:  # vapor
            # 计算气相物性
            return {
                'density': PropsSI('D', 'P', p, 'Q', 1, 'Water'),    # 密度
                'viscosity': PropsSI('V', 'P', p, 'Q', 1, 'Water'),  # 动力粘度
                'enthalpy': PropsSI('H', 'P', p, 'Q', 1, 'Water'),   # 比焓
                'specific_heat': PropsSI('C', 'P', p, 'Q', 1, 'Water'),  # 比热容
                'thermal_conductivity': PropsSI('L', 'P', p, 'Q', 1, 'Water')  # 导热系数
            }
    except Exception as e:
        print(f"警告：物性计算失败 (P={p}, T={t})")
        print(f"错误信息: {str(e)}")
        return None

def get_saturation_temperature(pressure):
    """
    计算给定压力下的饱和温度
    
    参数：
    pressure: float, 压力 (Pa)
    
    返回：
    float: 饱和温度 (K)
    """
    try:
        return PropsSI('T', 'P', pressure, 'Q', 0, 'Water')
    except Exception as e:
        print(f"警告：饱和温度计算失败 (P={pressure})")
        print(f"错误信息: {str(e)}")
        return DEFAULT_SATURATION_TEMP

def get_latent_heat(pressure):
    """
    获取给定压力下的汽化潜热
    
    参数：
    pressure: float, 压力 (Pa)
    
    返回：
    float: 汽化潜热 (J/kg)
    """
    try:
        h_f = PropsSI('H', 'P', pressure, 'Q', 0, 'Water')  # 饱和液焓
        h_g = PropsSI('H', 'P', pressure, 'Q', 1, 'Water')  # 饱和气焓
        return h_g - h_f
    except Exception as e:
        print(f"警告：汽化潜热计算失败 (P={pressure})")
        print(f"错误信息: {str(e)}")
        return DEFAULT_LATENT_HEAT

def get_temperature_from_enthalpy(h, p, phase):
    """
    根据焓值和压力计算温度
    
    参数：
    h: float, 比焓 (J/kg)
    p: float, 压力 (Pa)
    phase: str, 相态 ('liquid' 或 'vapor')
    
    返回：
    float: 温度 (K)
    """
    try:
        return PropsSI('T', 'H', h, 'P', p, 'Water')
    except Exception as e:
        print(f"警告：温度计算失败 (h={h}, P={p})")
        if phase == 'liquid':
            return 300.0  # 返回默认液相温度
        else:
            return DEFAULT_SATURATION_TEMP  # 返回默认气相温度

def calculate_hydraulic_diameter(flow_area, wetted_perimeter):
    """
    计算水力直径
    
    参数：
    flow_area: float, 流通面积 (m²)
    wetted_perimeter: float, 湿周 (m)
    
    返回：
    float: 水力直径 (m)
    """
    return 4.0 * flow_area / wetted_perimeter

def calculate_reynolds_number(velocity, hydraulic_diameter, density, viscosity):
    """
    计算雷诺数
    
    参数：
    velocity: float, 流速 (m/s)
    hydraulic_diameter: float, 水力直径 (m)
    density: float, 密度 (kg/m³)
    viscosity: float, 动力粘度 (Pa·s)
    
    返回：
    float: 雷诺数
    """
    return abs(velocity) * hydraulic_diameter * density / viscosity

def calculate_friction_factor(reynolds_number):
    """
    计算摩擦因子
    
    参数：
    reynolds_number: float, 雷诺数
    
    返回：
    float: 摩擦因子
    """
    if reynolds_number < 2300:  # 层流
        return 64.0 / reynolds_number
    else:  # 湍流
        return 0.316 * reynolds_number**(-0.25)

def calculate_nusselt_number(reynolds_number, prandtl_number, is_heating=True):
    """
    计算努塞尔数
    
    参数：
    reynolds_number: float, 雷诺数
    prandtl_number: float, 普朗特数
    is_heating: bool, 是否为加热工况
    
    返回：
    float: 努塞尔数
    """
    if reynolds_number < 2300:  # 层流
        return 4.36  # 假设充分发展的层流
    else:  # 湍流
        n = 0.4 if is_heating else 0.3  # 加热/冷却的指数
        return 0.023 * reynolds_number**0.8 * prandtl_number**n
